package com.tinem.platform.module.starter.jpa.converter;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import lombok.SneakyThrows;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.usertype.DynamicParameterizedType;
import org.hibernate.usertype.UserType;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Properties;

/**
 * @author fzh
 * @version v1
 * @program: platform
 * @className EnumType
 * @description TODO
 * @site 
 * @company 
 * @create 2020-08-24 18:20
 */
public class EnumType<E extends Enum<?>> implements UserType, DynamicParameterizedType {

    private Class enumClass;
    private Method method;
    @Override
    public void setParameterValues(Properties properties) {
        ParameterType parameterType = (ParameterType) properties.get(DynamicParameterizedType.PARAMETER_TYPE);
        enumClass = parameterType.getReturnedClass();
        method = ReflectUtil.getMethod(enumClass,"valueOf",String.class);
    }

    @Override
    public int[] sqlTypes() {
        return new int[Types.CHAR];
    }

    @Override
    public Class returnedClass() {
        return enumClass;
    }

    @Override
    public boolean equals(Object o, Object o1) throws HibernateException {
        return ObjectUtil.equal(o,o1);
    }

    @Override
    public int hashCode(Object o) throws HibernateException {
        if(o == null){
            return 0;
        }
        return o.hashCode();
    }

    @SneakyThrows
    @Override
    public Enum nullSafeGet(ResultSet resultSet, String[] names, SharedSessionContractImplementor sharedSessionContractImplementor, Object o) throws HibernateException, SQLException {
        String v = resultSet.getString(names[0]);
        return ReflectUtil.invokeStatic(method,v);
    }

    @Override
    public void nullSafeSet(PreparedStatement preparedStatement, Object o, int i, SharedSessionContractImplementor sharedSessionContractImplementor) throws HibernateException, SQLException {
        preparedStatement.setObject(i,(String.valueOf(o)),Types.CHAR);
    }

    @Override
    public Object deepCopy(Object o) throws HibernateException {
        return o;
    }

    @Override
    public boolean isMutable() {
        return false;
    }

    @Override
    public Serializable disassemble(Object o) throws HibernateException {
        return (Serializable)o;
    }

    @Override
    public Object assemble(Serializable serializable, Object o) throws HibernateException {
        return o;
    }

    @Override
    public Object replace(Object o, Object o1, Object o2) throws HibernateException {
        return o;
    }
}
